package 多线程.阻塞与唤醒;


import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;

public class Main {
    public static void main(String[] args) {
//        m1();
        m2();
//        m3();
//        lockAwaitSignal();
    }

    /**
     * wait 与 notify 必须在synchronized块里面,否则就抛异常IllegalMonitorStateException
     * 必须先 wait 后 notify 否则 wait 的线程不能唤醒
     */
    private static void m1() {
        Object o = new Object();
        new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + " start");
            synchronized (o) {
                try {
                    o.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName() + " end");
        }, "a").start();
//        MyThreadUtils.sleep(1000);
        new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + " start");
            synchronized (o) {
                o.notify();
            }
            System.out.println(Thread.currentThread().getName() + " end");
        }, "b").start();
    }

    /**
     * await signal 必须在lock块里
     * await signal 顺序不能调换
     */

    private static void m2() {
        Lock lock = new ReentrantLock();
        Condition condition = lock.newCondition();
//        Lock lock = new ReentrantLock();
//        Condition condition = lock.newCondition();
        new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + " start");
            try {
//                lock.lock();
                condition.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
//            } finally {
//                lock.unlock();
//            }
            System.out.println(Thread.currentThread().getName() + " end");
        }, "a").start();
//        MyThreadUtils.sleep(1000);
        new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + " start");
//            try {
//                lock.lock();
            condition.signal();
//            } finally {
//                lock.unlock();
//            }
            System.out.println(Thread.currentThread().getName() + " end");
        }, "b").start();
    }


    /**
     * 解决了上述2个痛点
     */
    private static void m3() {
        Thread main = Thread.currentThread();
        System.out.println(Thread.currentThread().getName() + " start");
        Thread a = new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + " start");
            LockSupport.park();
            System.out.println(Thread.currentThread().getName() + " end");
            LockSupport.unpark(main);
        }, "a");
        a.start();
//        MyThreadUtils.sleep(1000);
        Thread b = new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + " start");
            LockSupport.unpark(a);
            System.out.println(Thread.currentThread().getName() + " end");
        }, "b");
        b.start();
        LockSupport.park();
        System.out.println(Thread.currentThread().getName() + " end");
    }
}
